package weixinOperator

import (
	"crypto/sha1"
	"fmt"
	"gopkg.in/chanxuehong/wechat.v2/mp/core"
	"gopkg.in/chanxuehong/wechat.v2/mp/jssdk"
	"io"
	"net/url"
	"sort"
	"strings"
	"t11Lib/t11Errors"
	"t11Lib/t11Util"
	"time"
	"亚太-iot-服务器/conf"
)

//微信公众号相关信息
type MpAccount struct {
	accessTokenServer   core.AccessTokenServer
	wechatClient        *core.Client
	jssdkTicketSupplier JssdkTickerSupplier
}

type mpManager struct {
	dict map[string]*MpAccount
}

var MpManager = func() mpManager {
	var accounts = make(map[string]*MpAccount)
	wxCfgs := conf.WxCfgManager.GetAll()
	for k, v := range wxCfgs {
		mpAccount := &MpAccount{}
		if v.AccessTokenReqtUrl == "" {
			mpAccount.accessTokenServer = core.NewDefaultAccessTokenServer(k, v.AppSecret, nil)
		} else {
			mpAccount.accessTokenServer = AccessTokenServerByOther{
				FetchUrl:        v.AccessTokenReqtUrl,
				AccessTokenPath: v.AccessTokenJsonPath,
			}
		}
		mpAccount.wechatClient = core.NewClient(mpAccount.accessTokenServer, nil)
		if v.JssdkTicketReqUrl == "" {
			mpAccount.jssdkTicketSupplier = jssdk.NewDefaultTicketServer(mpAccount.wechatClient)
		} else {
			mpAccount.jssdkTicketSupplier = &JssdkTicketServerByOther{
				FetchUrl:   v.JssdkTicketReqUrl,
				TicketPath: v.JssdkTicketJsonPath,
			}
		}
		accounts[k] = mpAccount
	}
	return mpManager{dict: accounts}
}()

func (self *mpManager) WechatClient(appId string) (*core.Client, t11Errors.T11Error) {
	mpAccount, ok := self.dict[appId]
	if ok {
		return mpAccount.wechatClient, nil
	} else {
		return nil, t11Errors.New("invalid appId: " + appId)
	}
}

func (self *mpManager) GetAccessToken(appId string) (string, t11Errors.T11Error) {
	mp, ok := self.dict[appId]
	if !ok {
		return "", t11Errors.New("非法的appId")
	}
	token, oerr := mp.accessTokenServer.Token()
	return token, t11Errors.Wrap(oerr)
}

//微信支付页面config签名
func wxJsTicketSign(mReq map[string]interface{}) string {

	//STEP 1, 对key进行升序排序.
	sorted_keys := make([]string, 0)
	for k, _ := range mReq {
		sorted_keys = append(sorted_keys, k)
	}

	sort.Strings(sorted_keys)

	//STEP2, 对key=value的键值对用&连接起来，略过空值
	var signStrings string
	for i, k := range sorted_keys {
		value := fmt.Sprintf("%v", mReq[k])
		if value != "" {
			if i != (len(sorted_keys) - 1) {
				signStrings = signStrings + k + "=" + value + "&"
			} else {
				signStrings = signStrings + k + "=" + value //最后一个不加此符号
			}
		}
	}

	//对字符串进行SHA1哈希
	t := sha1.New()
	io.WriteString(t, signStrings)
	upperSign := fmt.Sprintf("%x", t.Sum(nil))
	return upperSign
}

type JsApiTicketSign struct {
	Timestamp int64
	NonceStr  string
	Url       string
	Signature string
	AppId     string
}

//在Data["jsApiTicket"]中保存变量 JsApiTicketSign
func (self *mpManager) LoadJsapiTicket(appId string, reqUrl *url.URL) (*JsApiTicketSign, t11Errors.T11Error) {
	ticket := &JsApiTicketSign{}
	ticket.AppId = appId
	ticket.Url = reqUrl.String()
	idx := strings.LastIndex(ticket.Url, "#")
	if idx > 0 {
		ticket.Url = ticket.Url[:idx]
	}

	//ticket.Url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxf5966e14c79007f7&redirect_uri=http%3A%2F%2Fwx-dev.team11.cn%2Fwx%2Fwxdevice%2FconfigWifi&response_type=code&scope=snsapi_userinfo&state=STATE"
	err := self.genJsApiSignature(appId, ticket)
	return ticket, err
}

func (self *mpManager) genJsApiSignature(appId string, sign *JsApiTicketSign) t11Errors.T11Error {
	mp, ok := self.dict[appId]
	if !ok {
		return t11Errors.New("非法的appId")
	}

	ticket, err := mp.jssdkTicketSupplier.Ticket()
	if err != nil {
		return t11Errors.Wrap(err, "获取jsApiTicket失败")
	}
	if sign == nil || len(sign.Url) == 0 {
		return t11Errors.New("非法的签名结构")
	}
	if len(sign.NonceStr) == 0 {
		sign.NonceStr = t11Util.RandMd5()
	}
	if sign.Timestamp == 0 {
		sign.Timestamp = time.Now().Unix()
	}
	n := make(map[string]interface{}, 0)
	n["noncestr"] = sign.NonceStr
	n["jsapi_ticket"] = ticket
	n["timestamp"] = sign.Timestamp
	n["url"] = sign.Url
	sign.Signature = wxJsTicketSign(n)
	return nil
}
